//===============================================================================
// Microsoft patterns & practices
// Mobile Client Software Factory - July 2006
//===============================================================================
// Copyright  Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//===============================================================================

using System;
using System.CodeDom;
using System.Collections.Generic;
using System.Configuration;
using System.Globalization;
using System.Text;
using System.Reflection;
using Microsoft.Cci;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.Mobile.ObjectBuilder;

namespace Microsoft.Practices.ObjectBuilder.ObGen
{
	public abstract class MethodBaseDependencyPolicyGenerator : DependencyPolicyGenerator
	{
		protected CodeMemberMethod GenerateGetParametersMethod(string methodName, ParameterList parameters)
		{
			// object[]
			CodeTypeReference objectArray = new CodeTypeReference(new CodeTypeReference(typeof(object)), 1);

			// private static object[] GetParameters(IBuilderContext context, string id)
			CodeMemberMethod getParameters = new CodeMemberMethod();
			getParameters.Name = methodName;
			getParameters.Attributes = MemberAttributes.Private | MemberAttributes.Static;
			getParameters.ReturnType = objectArray;
			getParameters.Parameters.Add(new CodeParameterDeclarationExpression(typeof(IBuilderContext), "context"));
			getParameters.Parameters.Add(new CodeParameterDeclarationExpression(typeof(string), "id"));

			//    object[] parameters = new object[i];
			getParameters.Statements.Add(new CodeVariableDeclarationStatement(
				objectArray, "parameters", new CodeArrayCreateExpression(objectArray, parameters.Length)));

			for (int i = 0; i < parameters.Length; i++)
			{
				Parameter parameter = parameters[i];
				Type parameterType = parameter.Type.GetRuntimeType();

				string attributeVarName = "attribute" + i;
				CodeStatementCollection attributeBuildup = BuildAttributeCreationStatements(
					GetInjectionAttribute(parameter.Attributes, true),
					attributeVarName);
				getParameters.Statements.AddRange(attributeBuildup);

				// parameters[1] = attribute1.CreateParameter(typeof(IService)).GetValue(context);
				getParameters.Statements.Add(
					new CodeAssignStatement(
					// parameters[i]
						new CodeArrayIndexerExpression(
							new CodeVariableReferenceExpression("parameters"), new CodePrimitiveExpression(i)
						),
					// .GetValue
						new CodeMethodInvokeExpression(
					// .CreateParameter(typeof(IService))
							new CodeMethodInvokeExpression(
								new CodeVariableReferenceExpression(attributeVarName),
								"CreateParameter",
								new CodeTypeOfExpression(parameterType)
							),
							"GetValue",
					// (context);
							new CodeArgumentReferenceExpression("context")
						)
					)
				);
			}

			getParameters.Statements.Add(new CodeMethodReturnStatement(new CodeVariableReferenceExpression("parameters")));

			return getParameters;
		}
	}
}